Instance Store-Backed なインスタンスから EBS-Backed 向けのAMIをつくる
こんにちは、ももんが大好きの小山です。きょうは、Instance Store-Backed で起動しているインスタンスから Amazon EBS-Backed なAMIを作成する手順についてご紹介しようと思います。
前提
EC2のインスタンスを起動するとき、2つの方法があります。ハイパーバイザーに内蔵 (*イメージです) されたストレージにAMIの内容をコピーして起動する方法と、ハイパーバイザーとは別に設置されたストレージにAMIの内容をコピーして起動する方法です。前者の方法で起動するインスタンスを Instance Store-Backed インスタンスと呼び、後者の方法で起動するインスタンスを EBS-Backed インスタンスと呼びます。
Instance Store-Backed インスタンスでは、起動ディスクとしてインスタンスストア (Ephemeral Storage) を使います。インスタンスストアの中身は、インスタンスの停止と同時に削除されます。なぜなら、次に起動するとき同じハイパーバイザー (とその内蔵ストレージ) に当たるとは限らないからです。ですから、 Instance Store-Backed なインスタンスでは停止とターミネートがイコールです。
EBS-Backed なインスタンスでは、インスタンスの停止でストレージの内容が失われることはありません。どのハイパーバイザーに当たったとしても、EBSが置かれるのはハイパーバイザーの外だからです。インスタンスストアはハイパーバイザーの内蔵ストレージ、EBSはネットワークストレージのようなものだと考えればわかりやすいのではないでしょうか?
くどいようですが、Instance Store-Backed なインスタンスを停止しておいて後で起動することはできません。これは、ときどきAWS側でスケジュールされるメンテナンスが理由であっても同じことです。もう長いこと動き続けている Instance Store-Backed インスタンスにメンテナンスがスケジュールされて ぎょっ とした方、いらっしゃるんじゃないでしょうか?「そのインスタンス、どうやって設定したか覚えてないんだけど...」
消えて困るものをインスタンスストアに置く使い方を擁護するつもりはありませんが、もうメンテナンスが迫っているのに理想論ばかり並べていたのでは始まりません。そういうことで、とりあえずメンテナンスを乗り越えてアーキテクチャを見直すまでのつなぎとして使える方法をご紹介します。Amazon Linux AMI 限定です。
準備
元になるインスタンス (Instance Store-Backed) でアップデートを実行します。今回の検証では 東京リージョンのamzn-ami-pv-2013.03.0.x86_64.manifest.xml (ami-153fbf14)を使いましたが、アップデートなしで作成したAMIから起動したインスタンスはカーネルパニックを起こしていました。そういうものなんです。
アップデートできたら、EC2のマネジメントコンソールで新しいボリュームを2つ作成します。1つめは一時ファイル置き場兼バックアップとして使い、2つめは新しいAMIの元になるボリュームとして使います。1つ目のボリュームは gp2 である程度大きく (IOPSを稼いで作業時間を短縮するため)、2つ目は元になるインスタンス (インスタンスストア) の中身が丸々収まる大きさにします。インスタンスストアで使用中の領域が10GBなら1つ目のボリュームは100GB、2つ目は20GBくらい見ておくとよいでしょう。以降では、1つ目をボリューム1、2つ目をボリューム2と呼ぶことにします。ボリュームが作成できたら、それぞれ元になるインスタンス (Instance Store-Backed) へアタッチしましょう
ステップ1: コード証明書をつくる
いきなりなんの話をしているのかと思われるかもしれませんが、今回の手順では「実行中の Instance Store-Backed インスタンスから作成したAMIをS3に置く」ための公式ツールを流用して起動ディスクをイメージ化しています。こうすることによって、ただでさえ無茶である「実行中のインスタンスから起動ディスクのイメージを作成する」という目論みをごまかしているわけです。AMIをつくる時にはコード署名が必要になりますから、そのツールを使うにはコード証明書が必要なわけです。とにかく元になるインスタンスにログインしてコード証明書をつくります。
[ec2-user ~]$ openssl genrsa 2048 > /temp/cert/private-key.pem Generating RSA private key, 2048 bit long modulus ......+++ ....+++ e is 65537 (0x10001) [ec2-user ~]$ chmod 400 /temp/cert/private-key.pem [ec2-user ~]$ openssl req -new -x509 -nodes -sha256 -days 365 -key private-key.pem -outform PEM > certificate.pem You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [XX]: State or Province Name (full name) []: Locality Name (eg, city) [Default City]: Organization Name (eg, company) [Default Company Ltd]: Organizational Unit Name (eg, section) []: Common Name (eg, your name or your server's hostname) []: Email Address []: [ec2-user ~]$ ls /tmp/cert -l total 8 -rw-rw-r-- 1 ec2-user ec2-user 1212 20 avr 14:52 certificate.pem -r-------- 1 ec2-user ec2-user 1675 20 avr 14:51 private-key.pem
できました! 次に進みましょう。
ステップ2: イメージの作成
元になるインスタンスで、起動ディスクのイメージを作成してボリュームに保存します。まずはボリューム1をフォーマットしてマウントしましょう。以下では /dev/xvdf がアタッチしたボリューム1ですが、そうじゃないことの方が多いと思いますからかならずご自身の目で確かめてください!
[ec2-user ~]$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvdf 202:80 0 100G 0 disk xvdg 202:96 0 20G 0 disk xvda1 202:1 0 8G 0 disk / xvda2 202:2 0 149.1G 0 disk /media/ephemeral0 xvda3 202:3 0 896M 0 disk [SWAP] [ec2-user ~]$ sudo mkfs -t ext4 /dev/xvdf mke2fs 1.42.3 (14-May-2012) Étiquette de système de fichiers= Type de système d'exploitation : Linux Taille de bloc=4096 (log=2) Taille de fragment=4096 (log=2) « Stride » = 0 blocs, « Stripe width » = 0 blocs 6553600 i-noeuds, 26214400 blocs 1310720 blocs (5.00%) réservés pour le super utilisateur Premier bloc de données=0 Nombre maximum de blocs du système de fichiers=4294967296 800 groupes de blocs 32768 blocs par groupe, 32768 fragments par groupe 8192 i-noeuds par groupe Superblocs de secours stockés sur les blocs : 32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 4096000, 7962624, 11239424, 20480000, 23887872 Allocation des tables de groupe : complété Écriture des tables d'i-noeuds : complété Création du journal (32768 blocs) : complété Écriture des superblocs et de l'information de comptabilité du système de fichiers : complété [ec2-user ~]$ sudo mkdir /mnt/ebs [ec2-user ~]$ sudo mount /dev/xvdf /mnt/ebs
ボリューム1の用意ができましたので、以下の要領でボリューム1に起動ディスクのイメージを作成しましょう。
[ec2-user ~]$ sudo -E su [root ec2-user]# $EC2_AMITOOL_HOME/bin/ec2-bundle-vol -k /tmp/cert/private-key.pem -c /tmp/cert/certificate.pem -u 123456789012 -r x86_64 -e /tmp/cert -d /mnt/ebs Copying / into the image file /mnt/ebs/image... Excluding: /proc/sys/fs/binfmt_misc /dev/pts /mnt/ebs /proc /sys / /dev /media /mnt /proc /sys /tmp/cert /mnt/ebs/image /mnt/img-mnt 1+0 enregistrements lus 1+0 enregistrements écrits 1048576 octets (1.0 MB) copiés, 0.00223099 s, 470 MB/s mke2fs 1.42.3 (14-May-2012) Bundling image file... Splitting /mnt/ebs/image.tar.gz.enc... Created image.part.56 Generating digests for each part... Digests generated. Unable to read instance meta-data for ancestor-ami-ids Unable to read instance meta-data for ramdisk-id Unable to read instance meta-data for product-codes Creating bundle manifest... ec2-bundle-vol complete. [root ec2-user]# ls /mnt/ebs -l total 2375000 -rw-r--r-- 1 root root 10737418240 20 avr 17:43 image -rw-r--r-- 1 root root 10681 20 avr 17:51 image.manifest.xml -rw-r--r-- 1 root root 10485760 20 avr 17:50 image.part.00 ... -rw-r--r-- 1 root root 8897872 20 avr 17:50 image.part.56 drwx------ 2 root root 16384 20 avr 17:19 lost+found [root ec2-user]# exit [ec2-user ~]$
でかいファイルができていますね! これがお目当てのイメージです。
ステップ3: 書き出し
できあがったイメージをボリューム2へ書き出します。
[ec2-user ~]$ lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT xvdf 202:80 0 100G 0 disk /mnt/ebs xvdg 202:96 0 20G 0 disk xvda1 202:1 0 8G 0 disk / xvda2 202:2 0 149.1G 0 disk /media/ephemeral0 xvda3 202:3 0 896M 0 disk [SWAP] [ec2-user ~]$ sudo dd if=/mnt/ebs/image of=/dev/xvdg bs=1M 10240+0 enregistrements lus 10240+0 enregistrements écrits 10737418240 octets (11 GB) copiés, 286.77 s, 37.4 MB/s [ec2-user ~]$ sudo partprobe /dev/sdb [ec2-user ~]$ sudo umount /dev/ebs
これで起動可能なボリュームができているはずですが、ドキュメントには /etc/fstab にあるインスタンスストアのエントリを削除するように記載がありました。ここでは、強調表示にした最後の2行を消しました。
[ec2-user ~]$ sudo mkdir /mnt/ebs [ec2-user ~]$ sudo mount /dev/xvdg /mnt/ebs [ec2-user ~]$ sudo nano /mnt/ebs/etc/fstab # LABEL=/ / ext4 defaults,noatime 1 1 tmpfs /dev/shm tmpfs defaults 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 sysfs /sys sysfs defaults 0 0 proc /proc proc defaults 0 0 /dev/sda2 /media/ephemeral0 auto defaults,comment=cloudconfig 0 2 /dev/sda3 none swap sw,comment=cloudconfig 0 0 [ec2-user ~]$ sudo unmount /ebs
アンマウントして完成です!
ステップ5: EBS-Backed Instance 用のAMIの作成
ボリューム2からスナップショットを撮って...
AMIにします。
もちろん起動するインスタンスは EBS-Backed
やりました!
おわりに
いかがでしたか? ご紹介した手順はかなり面倒な上、これで起動したインスタンスはちょっと不安ですよね... もう少し真っ当な方法をご存知の方はぜひ教えてください!
Instance Store-Backed Linux AMI の作成 - Amazon Elastic Compute Cloud http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/creating-an-ami-instance-store.html